// 异步钩子 -- 串联promise
class AsyncSeriesHook {
  // args => ['name']
  constructor(args) {
    this.tasks = [];
  }
  tapAsync(name, task) {
    this.tasks.push(task);
  }
  tapPromise(name, task) {
    this.tasks.push(task);
  }
  callAsync(...args) {
    let finalCallback = args.pop();
    let index = 0;
    let next = (message) => {
      if (this.tasks.length === index) return finalCallback(message);
      let task = this.tasks[index++];
      let rest = task(...args, next);
      if (rest instanceof Promise) {
        rest.then(() => next()).catch((error) => next(error));
      }
    };
    next();
  }
  // 仅支持promise队列
  promise(...args) {
    let [first, ...others] = this.tasks;
    return others.reduce((p, n) => {
      // redux源码
      return p.then(() => n(...args));
    }, first(...args));
  }
}

const hook = new AsyncSeriesHook(["name"]);

console.time("cost");

// hook.tapAsync("hello", (name, cb) => {
//   setTimeout(() => {
//     console.log(`hello ${name}`);
//     cb();
//   }, 2000);
// });
hook.tapPromise("hello again", (name, cb) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`hello ${name}, again`);
      resolve();
    }, 5000);
  });
});
hook.tapPromise("hello two", (name, cb) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(`hello ${name}, two`);
      resolve();
      // reject("error");
    }, 1000);
  });
});

// hook.callAsync("前端小溪", (msg) => {
//   console.log("done", msg);
//   console.timeEnd("cost");
// });
hook.promise("前端小溪").then((msg) => {
  console.log("done", msg);
  console.timeEnd("cost");
});
